package com.ruoyi.tiktok.cos;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.transfer.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class qCosUtils {

    private static String secretId = "AKID6BC4kDSWOGzWqyugGdppiPtAF8B2hARV";
    private static String secretKey = "ykJenlaBZjj9NPFtLZbSBj5IKCsOsBLJ";
    private static String cosRegion = "ap-nanjing";
    private static String bucketName = "tuike-1254233287";


        private static TransferManager createTransferManager() {
            // 1 初始化用户身份信息(secretId, secretKey)
            // 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
            // 3 生成cos客户端
            COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
            ClientConfig clientConfig = new ClientConfig(new Region(cosRegion));
            clientConfig.setHttpProtocol(HttpProtocol.https);
            COSClient cosclient = new COSClient(cred, clientConfig);

            // 线程池配置
            ExecutorService threadPool = Executors.newFixedThreadPool(32);
            // 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
            TransferManager transferManager = new TransferManager(cosclient, threadPool);
            return transferManager;
        }

        // Prints progress while waiting for the transfer to finish.
        private static void showTransferProgress(Transfer transfer) {
            System.out.println(transfer.getDescription());
            do {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    return;
                }
                TransferProgress progress = transfer.getProgress();
                long so_far = progress.getBytesTransferred();
                long total = progress.getTotalBytesToTransfer();
                double pct = progress.getPercentTransferred();
                System.out.printf("[%d / %d] = %.02f%%\n", so_far, total, pct);
            } while (transfer.isDone() == false);
            System.out.println(transfer.getState());
        }


        public static void uploadFile() {
            TransferManager transferManager = createTransferManager();

            File localFile = new File("C:\\Users\\admin\\Desktop\\videos\\demo4.mp4");
            String key = "aaa/demo4.mp4";// 服务器上的地址

            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
            try {
                // 返回一个异步结果Upload, 可同步的调用waitForUploadResult等待upload结束, 成功返回UploadResult, 失败抛出异常.
                long startTime = System.currentTimeMillis();
                Upload upload = transferManager.upload(putObjectRequest);
                showTransferProgress(upload);
                UploadResult uploadResult = upload.waitForUploadResult();
                long endTime = System.currentTimeMillis();
                System.out.println("used time: " + (endTime - startTime) / 1000);
                System.out.println(uploadResult.getETag());
                System.out.println(uploadResult.getCrc64Ecma());
            } catch (CosServiceException e) {
                e.printStackTrace();
            } catch (CosClientException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            transferManager.shutdownNow();
        }

        // 上传文件（上传过程中暂停, 并继续上传)
        private static void pauseUploadFileAndResume() {
            TransferManager transferManager = createTransferManager();

            String key = "aaa/bbb.txt";
            File localFile = new File("src/resources/len30M.txt");
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
            try {
                // 返回一个异步结果Upload, 可同步的调用waitForUploadResult等待upload结束, 成功返回UploadResult, 失败抛出异常.
                Upload upload = transferManager.upload(putObjectRequest);
                Thread.sleep(10000);
                PersistableUpload persistableUpload = upload.pause();
                upload = transferManager.resumeUpload(persistableUpload);
                showTransferProgress(upload);
                UploadResult uploadResult = upload.waitForUploadResult();
                System.out.println(uploadResult.getETag());
            } catch (CosServiceException e) {
                e.printStackTrace();
            } catch (CosClientException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            transferManager.shutdownNow();
        }

        public static void multipartUploadWithMetaData(String parentFolder, MultipartFile multipartFile) throws IOException {
            TransferManager transferManager = createTransferManager();

            //String key = "aaa/bbb.txt";
            //File localFile = new File("src/test/resources/len20M.txt");

            ObjectMetadata objectMetadata = new ObjectMetadata();
            Map<String, String> userMeta = new HashMap<String, String>();
            userMeta.put("usermeta", "hello-mult");
            objectMetadata.setUserMetadata(userMeta);

            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, parentFolder, multipartFile.getInputStream(), objectMetadata);
            putObjectRequest.withMetadata(objectMetadata);
            try {
                // 返回一个异步结果Upload, 可同步的调用waitForUploadResult等待upload结束, 成功返回UploadResult, 失败抛出异常.
                long startTime = System.currentTimeMillis();
                Upload upload = transferManager.upload(putObjectRequest);
                showTransferProgress(upload);
                UploadResult uploadResult = upload.waitForUploadResult();
                long endTime = System.currentTimeMillis();
                System.out.println("used time: " + (endTime - startTime) / 1000);
                System.out.println(uploadResult.getETag());
                System.out.println(uploadResult.getCrc64Ecma());
            } catch (CosServiceException e) {
                e.printStackTrace();
            } catch (CosClientException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            transferManager.shutdownNow();
        }

        // 批量上传
        private static void uploadDirectory() {
            TransferManager transferManager = createTransferManager();

            // 设置文件上传到 bucket 之后的前缀目录，设置为 “”，表示上传到 bucket 的根目录
            String cos_path = "/prefix";
            // 要上传的文件夹的绝对路径
            String dir_path = "/to/mydir";
            // 是否递归上传目录下的子目录，如果是 true，子目录下的文件也会上传，且cos上会保持目录结构
            Boolean recursive = false;

            try {
                // 返回一个异步结果Upload, 可同步的调用waitForUploadResult等待upload结束, 成功返回UploadResult, 失败抛出异常.
                MultipleFileUpload upload = transferManager.uploadDirectory(bucketName, cos_path, new File(dir_path), recursive);

                // 可以选择查看上传进度
                showTransferProgress(upload);

                // 或者阻塞等待完成
                upload.waitForCompletion();

                System.out.println("upload directory done.");
            } catch (CosServiceException e) {
                e.printStackTrace();
            } catch (CosClientException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            transferManager.shutdownNow();
        }

        // 批量下载
        private static void downloadDirectory() {
            TransferManager transferManager = createTransferManager();

            // 设置要下载的对象的前缀（相当于cos上的一个目录），如果设置成 ""，则下载整个 bucket。
            String cos_path = "/prefix";
            // 要保存下载的文件的文件夹的绝对路径
            String dir_path = "/to/mydir";

            try {
                // 返回一个异步结果download, 可同步的调用waitForUploadResult等待download结束.
                MultipleFileDownload download = transferManager.downloadDirectory(bucketName, cos_path, new File(dir_path));

                // 可以选择查看下载进度
                showTransferProgress(download);

                // 或者阻塞等待完成
                download.waitForCompletion();

                System.out.println("download directory done.");
            } catch (CosServiceException e) {
                e.printStackTrace();
            } catch (CosClientException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            transferManager.shutdownNow();
        }

        // 将文件下载到本地
        private static void downLoadFile() {
            TransferManager transferManager = createTransferManager();

            String key = "aaa/bbb.txt";
            File downloadFile = new File("src/test/resources/download.txt");
            GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key);
            try {
                // 返回一个异步结果copy, 可同步的调用waitForCompletion等待download结束, 成功返回void, 失败抛出异常.
                Download download = transferManager.download(getObjectRequest, downloadFile);
                download.waitForCompletion();
            } catch (CosServiceException e) {
                e.printStackTrace();
            } catch (CosClientException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            transferManager.shutdownNow();
        }

        // 将文件下载到本地(中途暂停并继续开始)
        private static void pauseDownloadFileAndResume() {
            TransferManager transferManager = createTransferManager();

            String key = "aaa/bbb.txt";
            File downloadFile = new File("src/test/resources/download.txt");
            GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key);
            try {
                // 返回一个异步结果copy, 可同步的调用waitForCompletion等待download结束, 成功返回void, 失败抛出异常.
                Download download = transferManager.download(getObjectRequest, downloadFile);
                Thread.sleep(5000L);
                PersistableDownload persistableDownload = download.pause();
                download = transferManager.resumeDownload(persistableDownload);
                showTransferProgress(download);
                download.waitForCompletion();
            } catch (CosServiceException e) {
                e.printStackTrace();
            } catch (CosClientException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            transferManager.shutdownNow();
        }


        // copy接口支持根据文件大小自动选择copy或者分块copy
        // 以下代码展示跨园区拷贝, 即将一个园区的文件拷贝到另一个园区
        private static void copyFileForDiffRegion() {
            // 1 初始化用户身份信息(secretId, secretKey)
            COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
            // 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
            ClientConfig clientConfig = new ClientConfig(new Region(cosRegion));
            // 3 生成cos客户端
            COSClient cosclient = new COSClient(cred, clientConfig);

            ExecutorService threadPool = Executors.newFixedThreadPool(32);
            // 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
            TransferManager transferManager = new TransferManager(cosclient, threadPool);

            // 要拷贝的bucket region, 支持跨园区拷贝
            Region srcBucketRegion = new Region("ap-shanghai");
            // 源bucket, bucket名需包含appid
            String srcBucketName = "srcBucket-12500000000";
            // 要拷贝的源文件
            String srcKey = "aaa/bbb.txt";
            // 目的bucket, bucket名需包含appid
            String destBucketName = "destBucket-12500000000";
            // 要拷贝的目的文件
            String destKey = "ccc/ddd.txt";

            COSClient srcCOSClient = new COSClient(cred, new ClientConfig(srcBucketRegion));
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketRegion, srcBucketName,
                    srcKey, destBucketName, destKey);
            try {
                Copy copy = transferManager.copy(copyObjectRequest, srcCOSClient, null);
                // 返回一个异步结果copy, 可同步的调用waitForCopyResult等待copy结束, 成功返回CopyResult, 失败抛出异常.
                CopyResult copyResult = copy.waitForCopyResult();
            } catch (CosServiceException e) {
                e.printStackTrace();
            } catch (CosClientException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            transferManager.shutdownNow();
            srcCOSClient.shutdown();
            cosclient.shutdown();
        }

        // copy接口支持根据文件大小自动选择copy或者分块copy
        // 以下代码展示同园区拷贝, 即将同园区的文件拷贝到另一个园区
        private static void copyFileForSameRegion() {
            TransferManager transferManager = createTransferManager();
            TransferManagerConfiguration transferManagerConfiguration = new TransferManagerConfiguration();
            transferManagerConfiguration.setMultipartCopyThreshold(20*1024*1024);
            transferManager.setConfiguration(transferManagerConfiguration);

            // 要拷贝的bucket region, 支持跨园区拷贝
            Region srcBucketRegion = new Region("ap-beijing-1");
            // 源bucket, bucket名需包含appid
            String srcBucketName = "srcBucket-12500000000";
            // 要拷贝的源文件
            String srcKey = "aaa/bbb.txt";
            // 目的bucket, bucket名需包含appid
            String destBucketName = "destBucket-12500000000";
            // 要拷贝的目的文件
            String destKey = "ccc/ddd.txt";

            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketRegion, srcBucketName,
                    srcKey, destBucketName, destKey);
            try {
                Copy copy = transferManager.copy(copyObjectRequest);
                // 返回一个异步结果copy, 可同步的调用waitForCopyResult等待copy结束, 成功返回CopyResult, 失败抛出异常.
                CopyResult copyResult = copy.waitForCopyResult();
                System.out.println(copyResult.getCrc64Ecma());
            } catch (CosServiceException e) {
                e.printStackTrace();
            } catch (CosClientException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            transferManager.shutdownNow();
        }

        private static void copyFileSetMetadata() {
            // 1 初始化用户身份信息(secretId, secretKey)
            COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
            // 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
            ClientConfig clientConfig = new ClientConfig(new Region(cosRegion));
            // 3 生成cos客户端
            COSClient cosclient = new COSClient(cred, clientConfig);

            ClientConfig srcClientConfig = new ClientConfig(new Region("ap-shanghai"));
            COSClient srcCosclient = new COSClient(cred, srcClientConfig);

            ExecutorService threadPool = Executors.newFixedThreadPool(2);
            // 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
            TransferManager transferManager = new TransferManager(cosclient, threadPool);
            TransferManagerConfiguration transferManagerConfiguration = new TransferManagerConfiguration();
            transferManagerConfiguration.setMultipartCopyThreshold(5*1024*1024);
            transferManager.setConfiguration(transferManagerConfiguration);

            // 要拷贝的bucket region, 支持跨园区拷贝
            Region srcBucketRegion = new Region("ap-shanghai");
            // 源bucket, bucket名需包含appid
            String srcBucketName = "mysrcbucket-123456789";
            // 要拷贝的源文件
            String srcKey = "aaa/bbb.txt";
            // 目的bucket, bucket名需包含appid
            String destBucketName = "mydestbucekt-123456789";
            // 要拷贝的目的文件
            String destKey = "bbb/ccc.txt";

            ObjectMetadata objectMetadata = new ObjectMetadata();
            Map<String, String> userMeta = new HashMap<String, String>();
            userMeta.put("usermeta", "hello-mult-copy");
            objectMetadata.setUserMetadata(userMeta);

            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketRegion, srcBucketName,
                    srcKey, destBucketName, destKey);
            System.out.println(copyObjectRequest.getDestinationBucketName());
            copyObjectRequest.setNewObjectMetadata(objectMetadata);
            try {
                Copy copy = transferManager.copy(copyObjectRequest, srcCosclient, null);
                // 返回一个异步结果copy, 可同步的调用waitForCopyResult等待copy结束, 成功返回CopyResult, 失败抛出异常.
                //showTransferProgress(copy);
                CopyResult copyResult = copy.waitForCopyResult();
                System.out.println(copyResult.getCrc64Ecma());
            } catch (CosServiceException e) {
                e.printStackTrace();
            } catch (CosClientException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            transferManager.shutdownNow();
            cosclient.shutdown();
        }

        private static void resumableDownloadFile() {
            TransferManager transferManager = createTransferManager();

            GetObjectRequest getObj = new GetObjectRequest(bucketName, "/path/to/key");

            File dstFile = new File("dstFile");
            Download download = transferManager.download(getObj, dstFile, true);
            showTransferProgress(download);
            try {
                download.waitForCompletion();
            } catch (CosServiceException e) {
                e.printStackTrace();
            } catch (CosClientException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            transferManager.shutdownNow();
        }


}
